package com.yl.module.common.service.impl;

import cn.hutool.core.util.StrUtil;
import com.yl.common.core.redis.RedisCache;
import com.yl.module.common.domain.SystemCommon;
import com.yl.module.common.service.SystemCommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class SystemCommonServiceImpl implements SystemCommonService {

	@Autowired
	RedisCache redisCache;

	@Override
	public String getUniqueNum(
			String businessPrefix,
			String redisKey,
			Integer redisNumLength,
			Integer randomNumLength
	){
		/*
		此方法理论上存在的漏洞
		如果redis宕机了 可能存在最终生成的唯一数重复 不过这种概率很小 不大的业务场景可以使用
		 */
		if(StrUtil.isBlank(businessPrefix)||StrUtil.isBlank(redisKey)){
			throw new RuntimeException("参数businessPrefix、redisKey不能为空");
		}
		if(null==redisNumLength||redisNumLength.equals(0)){
			redisNumLength = SystemCommon.UniqueNumLengthEnum.LENGTH5.getCode();
		}
		if(null==randomNumLength||randomNumLength.equals(0)){
			randomNumLength = SystemCommon.UniqueNumLengthEnum.LENGTH3.getCode();
		}

		//获取日期
		LocalDateTime now = LocalDateTime.now();
		String yyyyMMddHHmm = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));

		//获取随机数
		String randomNum = String.format(
				"%0"+randomNumLength+"d",
				//(int) Math.pow(10, randomNumLength + 1) 表示10的randomNumLength次方
				ThreadLocalRandom.current().nextInt(1, (int) Math.pow(10, randomNumLength)));

		//获取redis自增数
		Long increment = redisCache.increment(redisKey, 1);
		if(Objects.isNull(increment)){
			throw new RuntimeException("redis获取自增键异常");
		}
		// 如果这是第一次设置键，则为其设置过期时间
		if (increment == 1L) {
			// 获取当天的 23:59:59 过期
			LocalDateTime endOfDay = LocalDateTime.of(now.toLocalDate(), LocalTime.of(23, 59, 59));
			redisCache.expire(redisKey, Duration.between(now, endOfDay).getSeconds(), TimeUnit.SECONDS);
		}
		String redisNum = String.format("%0"+redisNumLength+"d", increment);

		return businessPrefix+yyyyMMddHHmm+randomNum+redisNum;
	}

	@Override
	public String getUniqueNum(
			String businessPrefix,
			String redisKey
	){
		return getUniqueNum(
				businessPrefix,
				redisKey,
				SystemCommon.UniqueNumLengthEnum.LENGTH5.getCode(),
				SystemCommon.UniqueNumLengthEnum.LENGTH3.getCode()
		);
	}






}



